function JSON2String(obj){
	if ( obj == null  ){
	  return "null";
	}
	if (typeof obj == "number"){
		return isFinite(obj) ? String(obj) : "null";
	}
	if (typeof obj == "boolean"){
		return String(obj);
	}
	if (typeof obj == "date"){
		function f(n) {
            return n < 10 ? '0' + n : n;
        }
        return '"' + obj.getFullYear() + '-' +
                f(obj.getMonth() + 1) + '-' +
                f(obj.getDate()) + 'T' +
                f(obj.getHours()) + ':' +
                f(obj.getMinutes()) + ':' +
                f(obj.getSeconds()) + '"';
	}
	if (typeof obj == "array" || obj instanceof Array){
		var a = ['['],  // The array holding the text fragments.
            b,          // A boolean indicating that a comma is required.
            i,          // Loop counter.
            l = obj.length,
            v;          // The value to be stringified.

        function array_p(s) {
            if (b) {
                a.push(',');
            }
            a.push(s);
            b = true;
        }
        for (i = 0; i < l; i += 1) {
            v = obj[i];
            switch (typeof v) {
            case 'undefined':
            case 'function':
            case 'unknown':
                break;
            case 'object':
            default:
                array_p(JSON2String(v));
            }
        }
        a.push(']');
        return a.join('');
	}
	if (typeof obj == "string" || obj instanceof String){
		var m = {
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"' : '\\"',
            '\\': '\\\\'
        };
		if (/["\\\x00-\x1f]/.test(obj)) {
	        return '"' + obj.replace(/([\x00-\x1f\\"])/g, function(a, b) {
	            var c = m[b];
	            if (c) {
	                return c;
	            }
	            c = b.charCodeAt();
	            return '\\u00' +
	                Math.floor(c / 16).toString(16) +
	                (c % 16).toString(16);
	        }) + '"';
	    }
	    return '"' + obj + '"';
	}
	if (typeof obj == "object"){
		var a = ['{'],  // The array holding the text fragments.
            b,          // A boolean indicating that a comma is required.
            k,          // The current key.
            v;          // The current value.

        function object_p(s) {
            if (b) {
                a.push(',');
            }
            a.push(JSON2String(k), ':', s);
            b = true;
        }
        for (k in obj) {
            if (obj.hasOwnProperty(k)) {
                v = obj[k];
                switch (typeof v) {
                case 'undefined':
                case 'function':
                case 'unknown':
                    break;
                case 'object':
                default:
                    object_p(JSON2String(v));
                }
            }
        }
        a.push('}');
        return a.join('');
	}
}

/**
 * <p>将js对象转换为JSON字符串</p>
 * 
 * @param {Object}
 *            obj
 */
function formatNative(obj){
	return JSON2String(obj);
}	

/**
 * <p>判段对象是否可用</p>
 * @function
 * @param {Object}
 *            obj
 */
function isAvailable(obj)
{	
	if ( obj === undefined ) { return false; };
	if ( obj === null ) { return false; }
	if ( obj === "" ) { return false; };
	return true;
}	

/**
 * <p>构造 zxt.data.DataAbstract 对象.</p>
 * 
 * @class 基类
 *        zxt.data.DataSheet,zxt.data.DataWrapper,zxt.data.DataSheetColumn,eiblockmeta都继承于此类
 * @return A new zxt.data.DataAbstract
 */
zxt.data.DataAbstract = function() {
  /**
	 * <p>类的属性</p>
	 * 
	 * @type Object
	 * @private
	 */
  this._attrs = {};	
};

zxt.data.DataAbstract.prototype = new zxt.clazz();

/**
 * <p>根据属性名得到属性值</p>
 * @function
 * @param {String}
 *            prop : 属性名
 * @return {Object} : 属性名对应的值
 */
zxt.data.DataAbstract.prototype.get = function ( prop ) {
	return this._attrs[prop];	
};
	
/**
 * <p>设置属性值</p>
 * @function
 * @param {Object}
 *            prop : 属性名
 * @param {Object}
 *            value ： 属性名对应的值
 */
zxt.data.DataAbstract.prototype.set = function( prop, value ) {
	this._attrs[prop] = value;	
};

/**
 * <p>[GETTER | SETTER]属性对象</p>
 * @function
 * @return {Object} : 属性对象
 */
zxt.data.DataAbstract.prototype.attrs = function(v){
	if ( v == undefined ){ return this._attrs; }
	this._attrs = v;	
};


/**
 * <p>设置列表头每列的属性</p>
 * @class zxt.data.DataSheetColumn 类构造函数
 * @extends zxt.data.DataAbstract
 * @constructor
 * @param {Object}
 *            name : zxt.data.DataSheetColumn 名称
 * @see zxt.data.DataAbstract zxt.data.DataAbstract is the base class for this
 */
zxt.data.DataSheetColumn = function( name ) {
	zxt.data.DataAbstract.call(this);
	
	/**
	 * @private
	 */
    this.pos = -1;//列索引
	/**
	 * @private
	 */	
	this.name = name;//列名ID
	/**
	 * @private
	 */	
	this.descName = "";//列描述
	/**
	 * @private
	 */	
	this.type = "C"; 
	/**
	 * @private
	 */              
	this.regex = null; 
	/**
	 * @private
	 */              
	this.formatter = null;    
	/**
	 * @private
	 */       
	this.editor = "text";  
	/**
	 * @private
	 */           
	this.minLength = 0;    
	/**
	 * @private
	 */       
	this.maxLength = Number.MAX_VALUE;       
	/**
	 * @private
	 */    
	this.primaryKey = false;      
	/**
	 * @private
	 */   
	this.nullable = true;     
	/**
	 * @private
	 */   
	this.visible = true;     
	/**
	 * @private
	 */        
	this.readonly = false;   
	/**
	 * @private
	 */        
	this.displayType = "text"; 
	/**
	 * @private
	 */
	this.errorPrompt = null;    
	/**
	 * @private
	 */    
	this.dateFormat = null;    
	/**
	 * @private
	 */    
	this.defaultValue = "";     
	/**
	 * @private
	 */ 
	this.validateType = null;     
	/**
	 * @private
	 */
	this.width = 96;  
	/**
	 * @private
	 */
	this.height = 18;   
	/**
	 * @private
	 */
	this.align = "left";   
	/**
	 * @private
	 */   
	this.blockName = null; 
	/**
	 * @private
	 */
	this.sourceName = null; 
	/**
	 * @private
	 */
	this.labelProperty = null; 
	/**
	 * @private
	 */   
	this.valueProperty = null; 
		
};


zxt.defineClazz(zxt.data.DataSheetColumn, zxt.data.DataAbstract);
/**
 * <p>元数据,列表头设置</p>
 * 
 * @class
 * @param {String}
 *            sBlockId block的ID
 */
zxt.data.DataSheetMeta = function(sheetId){
	zxt.data.DataAbstract.call(this);

	this._sheetId = sheetId;
	this._columns = {};
	this._description = "";
};


zxt.defineClazz(zxt.data.DataSheetMeta, zxt.data.DataAbstract);
/**
 * <p>[GETTER | SETTER]描述</p>
 * @function
 * @param {String}
 *            v
 */
zxt.data.DataSheetMeta.prototype.description = function(v){
	if ( v == undefined ){ return this._description; };
	this._description=v;
};


/**
 * <p>添加一列元数据，即列头</p>
 * @function
 * @param {zxt.data.DataSheetColumn}
 *            col
 */
zxt.data.DataSheetMeta.prototype.addColumn = function(col){
  if ( col.instanceOf(zxt.data.DataSheetColumn) )	{
		this._columns[col.name]=col;
  } else {
  	throw new Error("Can NOT add as an zxt.data.DataSheetColumn");
  } 	
};

/**
 * <p>根据名称获取一列的元数据</p>
 * @function
 * @param {String}
 *            name
 * @return {zxt.data.DataSheetColumn} 列索引、列名、列描述等zxt.data.DataSheetColumn对象
 */
zxt.data.DataSheetMeta.prototype.getColumn = function(name){	
	return this._columns[name];
};

/**
 * <p>获取block的ID</p>
 * @function
 * @return {String}
 */
zxt.data.DataSheetMeta.prototype.getSheetId = function(){	
	return this._sheetId;
};

/**
 * <p>获取所有的元数据，即列表头集合</p>
 * @function
 * @return {zxt.data.DataSheetColumn[]} 列表头
 */
zxt.data.DataSheetMeta.prototype.getColumns = function(){	
	return this._columns;
};

/**
 * <p>表示一个block</p>
 * 
 * @class
 * @param {Object}
 *            sheetId sheet的ID
 */
zxt.data.DataSheet = function(sheetId) {	
	zxt.data.DataAbstract.call(this);
	if( typeof sheetId == "string" ){
		this._sheetMeta = new zxt.data.DataSheetMeta(sheetId);
	} else if ( sheetId.instanceOf(zxt.data.DataSheetMeta) ){
		this._sheetMeta = sheetId;
	} else {
		throw new Error("Can NOT create block");
	};	

	this._rows = new Array();
};

zxt.defineClazz(zxt.data.DataSheet, zxt.data.DataAbstract);
/**
 * <p>获取元数据</p>
 * @function
 * @return {zxt.data.DataSheetMeta} 列表头
 */
zxt.data.DataSheet.prototype.sheetMeta = function(v){
	if ( v == undefined ){ return this._sheetMeta; };	
	this._sheetMeta = v;
};


/**
 * <p>增加一行</p>
 * @function
 * @param {Object[]} sRow 行数据
 *             
 */
zxt.data.DataSheet.prototype.addRow = function(sRow){		
	if ( sRow == null ){
		this._rows.push([]);
	} else {
		this._rows.push(sRow);
	}		
};

/**
 * <p>获取所有行</p>
 * @function
 * @return {Object[]} 获取行记录集合
 */
zxt.data.DataSheet.prototype.getRows = function(){
	return this._rows;
};

/**
 * <p>根据行号和列名设置单元格的值</p>
 * @function
 * @param {int}
 *            sRowNo 行号
 * @param {String}
 *            sColName 列名
 * @param {Object}
 *            sValue 参数值
 */	
zxt.data.DataSheet.prototype.setCell = function(sRowNo, sColName, sValue){
	var pos = this.sheetMeta().getColumn(sColName).pos;
	while (typeof(this._rows[sRowNo]) == "undefined") this.addRow(null);
	this._rows[sRowNo][pos] = sValue;
};

/**
 * <p>根据行号和列名获取单元格的值</p>
 * @function
 * @param {int}
 *            sRowNo 行号
 * @param {String}
 *            sColName 列名
 */
zxt.data.DataSheet.prototype.getCell = function(sRowNo, sColName){
	var column = this.sheetMeta().getColumn(sColName);
	if (column) {
		var pos = this.sheetMeta().getColumn(sColName).pos;
		return this._rows[sRowNo][pos];
	} else {
		return "";
	}
};

/**
 * <p>根据行号和列索引设置单元格的值</p>
 * @function
 * @param {int}
 *            sRowNo 行号
 * @param {int}
 *            sColPos 列索引
 * @param {Object}
 *            sValue  字符串数值
 */
zxt.data.DataSheet.prototype.setCellByPos = function(sRowNo, sColPos, sValue){
	return this._rows[sRowNo][sColPos] = sValue;
};

/**
 * <p>根据行号和列索引获取单元格的值</p>
 * @function
 * @param {int}
 *            sRowNo 行号
 * @param {int}
 *            sColPos 列索引
 * @return {String} 单元格的值
 */
zxt.data.DataSheet.prototype.getCellByPos = function(sRowNo, sColPos){
	return this._rows[sRowNo][sColPos];
};

/**
 * <p>获得列表数据数组</p>
 * @function
 * @private
 * @param {Object}
 *            obj 包含列表头参数集合
 * @return {String[]} 列表数据数组
 */
zxt.data.DataSheet.prototype.getMappedArray = function(obj){
  var cols = this.sheetMeta().getColumns(); //列表头参数集合
  var row = new Array();
  for( var col in cols ){
    var pos = this.sheetMeta().getColumn(col).pos;//列索引
    row[pos] = obj[col];
  } 
  return row;
};	

/**
 * <p>获得列表某行的数据Object，以列名为下标</p>
 * @function
 * @private
 * @param {Object}
 *            row 包含某行数据的对象
 * @return {Object[]} 列表某行的数据Object,以列名(列表头ID)为下标
 */
zxt.data.DataSheet.prototype.getMappedObject = function(row){
	var cols = this.sheetMeta().getColumns();  
	var t = new Object();
	for(  var key in cols ){
		var col = cols[key];
		t[col.name] = row[col.pos];
	}
	return t;
};	

/**
 * <p>获得列表数据数组</p>
 * @function
 * @private
 */
zxt.data.DataSheet.prototype.getMappedRows = function(){  
	var ret = new Array();
	for(  var i = 0; i < this._rows.length; i++ ){
		var row = this._rows[i];
		var m = this.getMappedObject(row);
		ret.push(m);
	};
	return ret;
};
/**
 * @private
 */
zxt.data.DataSheet.prototype.clone = function(){
    return this;
};

/**
 * 前台EiInfo对象
 * 
 * @class
 * @param {String}
 *            sName EiInfo的名称
 */
zxt.data.DataWrapper = function(sName) {
	zxt.data.DataAbstract.call(this);

	this._name = null;  	
	this._message = null; 
	this._url = null;	
	this._method = null;	
	this._sheets = {};
	this._components = {};
	
	if( typeof sName == "string" ){
		this._name = sName;
	};  
};


zxt.defineClazz(zxt.data.DataWrapper, zxt.data.DataAbstract);
/**
 * <p>[GETTER | SETTER]名称</p>
 * @function
 * @param {String}
 * @return {String}  名称
 */
zxt.data.DataWrapper.prototype.name = function(v){
	if ( v == undefined ){ return this._name; };
	this._name = v;
};


/**
 * <p>[GETTER | SETTER] 提示消息</p>
 * @function
 * @param {String} 提示消息
 * @return {String}  提示消息
 *             
 */
zxt.data.DataWrapper.prototype.message = function(v){
	if ( v == undefined ){ return this._message; };
	this._message = v;
};

/**
 * <p>[GETTER | SETTER] 页面地址</p>
 * @function
 * @param {String} 页面地址
 * @return {String}  页面地址
 *             
 */
zxt.data.DataWrapper.prototype.url = function(v){
	if ( v == undefined ){ return this._url; };
	this._url = v;
};

/**
 * <p>[GETTER | SETTER] 操作方法</p>
 * @function
 * @param {String} 操作方法
 * @return {String}  操作方法
 *             
 */
zxt.data.DataWrapper.prototype.method = function(v){
	if ( v == undefined ){ return this._method; };
	this._method = v;
};

/**
 * <p>[GETTER | SETTER]属性对象</p>
 * @function
 * @param {Object} : 属性对象
 * @return {Object} : 属性对象
 */
zxt.data.DataWrapper.prototype.components = function(v){
	if ( v == undefined ){ return this._components; };
	this._components = v;	
};

/**
 * <P>把某一控件值封装到zxt.data.DataWrapper</p>
 * @function
 * @param v 控件ID
 * 
 */
zxt.data.DataWrapper.prototype.addComponent = function(v){
	var componentN = v;
	var component = $zxt.getComponent(componentN);
	var componentV = component.getValue();	
	this._components[componentN] = componentV; 
};	

/**
 * <P>把控件值封装到zxt.data.DataWrapper</p>
 * @function
 * @param v 控件ID
 * 
 */
zxt.data.DataWrapper.prototype.addComponents = function(v){
	var comps = $zxt.components();//获得注册的控件集合
	for(var v in comps){
		var comp = comps[v];
		if ( comp.instanceOf(zxt.ui.Interactor)){
			this._components[v] = comp.getValue();	
		};		
	};
};

/**
 * <P>把非Label的zxt.ui.Interactor控件值封装到zxt.data.DataWrapper</p>
 * @function
 * @param v 
 * 
 */
zxt.data.DataWrapper.prototype.addInputComponents = function(v){
	var comps = $zxt.components();
	for(var v in comps){
		var comp = comps[v];
		if ( comp.instanceOf(zxt.ui.Interactor)&& (!comp.instanceOf(zxt.ui.Label))){
			this._components[v] = comp.getValue();	
		};		
	};
};

/**
 * <P>渲染页面控件</p>
 * @function
 * 
 */
zxt.data.DataWrapper.prototype.populateComponents = function(){
	for(var v in this._components){
		var comp = $zxt.getComponent(v);
		if ( zxt.util.isValue(comp) ){
			if ( comp.instanceOf(zxt.ui.Interactor) ){
				var oldValue = comp.getValue();
				var value = this._components[v];
				var valueStr = value + "";
				if(oldValue == valueStr){
					continue;
				}
				comp.setValue(value);
				comp.render();
			};
		};		
	};
};

/**
 * <p>试图为传入的控件集合赋值、渲染</p>
 * @function
 * @param toRender 控件集
 */
zxt.data.DataWrapper.prototype.renderComponents = function(toRender){
	for(var i =0; i < toRender.length; i++){
		var comp_id = toRender[i].id;
		var comp = $zxt.getComponent(comp_id);
		if ( zxt.util.isValue(comp) ){
			if ( comp.instanceOf(zxt.ui.Interactor) ){
				var value = this._components[comp_id];
				comp.setValue(value);
				comp.render();
			}
		};		
	};
};

/**
 * <p>添加一个SHEET</p>
 * @function
 * @param {zxt.data.DataSheet}
 *            sheet
 */
zxt.data.DataWrapper.prototype.addSheet = function(sheet){
	this._sheets[sheet.sheetMeta().getSheetId()] = sheet;
};

/**
 * <p>根据ID获取SHEET</p>
 * @function
 * @param {String}
 *            sheetId 表格的ID
 * @return {zxt.data.DataSheet} Sheet对象
 */
zxt.data.DataWrapper.prototype.getSheet = function(sheetId){
	return this._sheets[sheetId];
};

/**
 * <p>获取所有的SHEET</p>
 * @function
 * @return {map}
 */
zxt.data.DataWrapper.prototype.getSheets = function(){
	return this._sheets;
};

/**
 * <p>设置EiInfo的扩展属性</p>
 * @function
 */
zxt.data.DataWrapper.prototype.set = function() {
	/* 按照块名、行号、列名三段式参数解析
	*arguments 是js 的保留字，用来引用Arguments对象,有length属性
	*arguments[0]表示第一个参数
	*/
	if (arguments.length == 2) {
		zxt.data.DataAbstract.prototype.set.call(this,arguments[0], arguments[1]);
		return;
	};
		
	var sSheet = arguments[0];
	if (typeof(this._sheets[sSheet]) == "undefined") {
		this._sheets[sSheet] = new zxt.data.DataSheet(sSheet);
	};
	
	if (arguments.length == 3) {		
		this._sheets[sSheet].set(arguments[1], arguments[2]);
		return;
	};
	
	if (arguments.length == 4) {
		if (typeof(this._sheets[sSheet].sheetMeta().getColumn(arguments[2]))  == "undefined") {
			var cc = new zxt.data.DataSheetColumn( arguments[2] );
	
			if (typeof(this._sheets[sSheet].sheetMeta().getColumns().length) == "undefined") {
				cc.pos = 0;	
			} else {
				cc.pos = this._sheets[sSheet].sheetMeta().getColumns().length;	
			};	  	
	
			this._sheets[sSheet].sheetMeta().addColumn(cc);
		};
		
		this._sheets[sSheet].setCell(arguments[1], arguments[2], arguments[3]);
		return;
	};
};

/**
 * <p>根据ID设置EiInfo的扩展属性</p>
 * @function
 * @param {String}
 *            id_in
 */
zxt.data.DataWrapper.prototype.setById = function(id_in) {
	var idArray = id_in.split("-");
	var value = $("#"+id_in).val();// ef.get(id_in).value;
	if ( idArray.length == 3) return this.set(idArray[0], idArray[1], idArray[2], value);
	if ( idArray.length == 2) return this.set(idArray[0], idArray[1], value);
	if ( idArray.length == 1) return this.set(idArray[0], value);
};


/**
 * <p>zxt.data.DataWrapper 2 Json</p>
 * @private
 * @ignore
 */
var EiInfoJsonConstants = {
	ATTRIBUTES                	: "attr",
	EIINFO_NAME                	: "name",
	EIINFO_MESSAGE             	: "msg",
	EIINFO_STATUS             	: "status",
	EIINFO_URL             	    : "url",
	EIINFO_METHOD               : "method",
	EIINFO_WIDGETS             	: "widgets",
	EIINFO_BLOCKS              	: "blocks",
	BLOCK_META                 	: "meta",	
	BLOCK_META_DESC            	: "desc",
	BLOCK_META_COLUMNLIST      	: "columns",
	BLOCK_META_COLUMNPOS       	: "columnPos",
	BLOCK_DATA                 	: "rows"
};


/**
 * <p>EiInfo到JSON字符串的转换帮助类</p>
 * 
 * @class
 */
function EiInfo2Json(){
};

/**
 * <p>将EiInfo转换成JSON字符串</p>
 * 
 * @param {EiInfo}
 *            sEiInfo Datarapper对象
 * @return {String} JSON字符串
 */
EiInfo2Json.EiInfo2JsonString = function(sEiInfo){	
	var a = ['{'];
	var appendComma;
	
	if ( isAvailable( sEiInfo.name() ) ){		
	  a.push( EiInfoJsonConstants.EIINFO_NAME, ':', formatNative( sEiInfo.name() ));
	  appendComma = true;
	};
	
	if ( isAvailable( sEiInfo.message() ) ){
		if (appendComma){ a.push(','); };		
		a.push( EiInfoJsonConstants.EIINFO_MESSAGE, ':', formatNative( sEiInfo.message() ));
		appendComma = true;
	};
	
	if ( isAvailable( sEiInfo.url() ) ){		
		if (appendComma){ a.push(','); };
		a.push( EiInfoJsonConstants.EIINFO_URL, ':', formatNative( sEiInfo.url() ));
		appendComma = true;
	};
	
	if ( isAvailable( sEiInfo.method() ) ){		
		if (appendComma){ a.push(','); };
		a.push( EiInfoJsonConstants.EIINFO_METHOD, ':', formatNative( sEiInfo.method() ));
		appendComma = true;
	};
	
	if ( isAvailable( sEiInfo.attrs() ) ){  
		if (appendComma){ a.push(','); };
	  a.push( EiInfoJsonConstants.ATTRIBUTES, ':', formatNative(sEiInfo.attrs()));
	  appendComma = true;
	};
	
	
	if (appendComma){ a.push(','); };
	a.push( EiInfoJsonConstants.EIINFO_WIDGETS, ':', formatNative(sEiInfo.components()));
	
  if (appendComma){ a.push(','); };
	a.push( EiInfoJsonConstants.EIINFO_BLOCKS, ':{');	
	var blocks = sEiInfo.getSheets();
	var b;
	for( var iKey in blocks ){
		var block = blocks[iKey];
		if (b) { a.push(','); };
		a.push( iKey, ':', EiInfo2Json.EiBlock2JsonString(block) );
		b = true;
	};	  
	a.push('}}');
  return a.join('');
};

/**
 * <p>把表格数据转成Json字符串</p>
 * @function
 * @private
 * @param {zxt.data.DataSheet}  zxt.data.DataSheet对象
 *            sSheet
 */
EiInfo2Json.EiBlock2JsonString = function(sSheet){	
	var a = ['{'];	
	
	a.push( EiInfoJsonConstants.ATTRIBUTES, ':', formatNative(sSheet.attrs()));
	a.push( ',', EiInfoJsonConstants.BLOCK_META, ':', EiInfo2Json.EiBlockMeta2JsonString( sSheet.sheetMeta() ) );
	
	a.push( ',', EiInfoJsonConstants.BLOCK_DATA, ':[');//"rows"
	
	var rows = sSheet.getRows();
	var b;
	for(var i=0;i<rows.length;i++){
		var row = rows[i];
		if (b) { a.push(','); };
		a.push('[');
		var c;
		for(var j=0;j<row.length;j++){
			if ( c ){ a.push(','); };
			a.push( formatNative(row[j]) );
			c = true;
		};
		b = true;
		c = false;
		a.push(']');
	};
	a.push(']}');
  return a.join('');
};

/**
 * <p>Blocks中的meta字段字符串转换处理</p>
 * @function
 * @private
 * @param {zxt.data.DataSheetMeta}
 *            sBlockMeta
 */
EiInfo2Json.EiBlockMeta2JsonString = function(sBlockMeta){	
	var a = ['{'];	
	var appendComma;
	if ( isAvailable( sBlockMeta.description() ) ){
	  a.push( EiInfoJsonConstants.BLOCK_META_DESC, ':', formatNative(sBlockMeta.description()));
	  appendComma = true;
	};
	if ( isAvailable( sBlockMeta.attrs() ) ){  
		if (appendComma){ a.push(','); };
	  a.push( EiInfoJsonConstants.ATTRIBUTES, ':', formatNative(sBlockMeta.attrs()));
	  appendComma = true;
	};
  if (appendComma){ a.push(','); };  
	a.push( EiInfoJsonConstants.BLOCK_META_COLUMNLIST, ':[');
	
	var columns = sBlockMeta.getColumns();
	var b;
	for( var iKey in columns ){
		var column = columns[iKey];
		if (b) { a.push(','); }
		a.push( EiInfo2Json.EiColumn2JsonString(column) );
		b = true;
	} ; 
	
	a.push(']}');
  return a.join('');
};

/**
 * <p>列名字符串转换处理</p>
 * @function
 * @private
 * @param {zxt.data.DataSheetColumn}
 *            sColumn
 */
EiInfo2Json.EiColumn2JsonString = function(sColumn){	
	var a = ['{'];	
	
	a.push( 'name', ':', formatNative(sColumn.name));
	
	a.push('}');
  return a.join('');
};

/**
 * <p>JSON对象到EiInfo转换的帮助类</p>
 * 
 * @class
 */
function Json2EiInfo(){
};

/**
 * <p>将字符串转换成EiInfo对象</p>
 * @function
 * @param {String}
 *            sJson
 * @return {zxt.data.DataWrapper}
 */
Json2EiInfo.parseString = function(sJson){
	var eiJson = eval( "("+ sJson +")" );
	return Json2EiInfo.parseJsonObject(eiJson);
};	

/**
 * <p>将对象转换成EiInfo对象</p>
 * @function
 * @param {Object}
 *            eiJson
 * @return {zxt.data.DataWrapper}
 */
Json2EiInfo.parseJsonObject = function(eiJson){    
    var eiInfo = new zxt.data.DataWrapper();
    
    var value = eiJson[EiInfoJsonConstants.EIINFO_NAME];
    if ( isAvailable( value ) ){
    	eiInfo.name( value );
    };	
    
    var value = eiJson[EiInfoJsonConstants.EIINFO_MESSAGE];
    if ( isAvailable( value ) ){
    	eiInfo.message( value );
    };
    
    var value = eiJson[EiInfoJsonConstants.EIINFO_URL];
    if ( isAvailable( value ) ){
    	eiInfo.url( value );
    };
    
    var value = eiJson[EiInfoJsonConstants.EIINFO_METHOD];
    if ( isAvailable( value ) ){
    	eiInfo.method( value );
    };
    
    var value = eiJson[EiInfoJsonConstants.ATTRIBUTES];
    if ( isAvailable( value ) ){
    	eiInfo.attrs( value );
    };
    
		var value = eiJson[EiInfoJsonConstants.EIINFO_WIDGETS];
    if ( isAvailable( value ) ){
    	eiInfo.components( value );
    };
		
    var value = eiJson[EiInfoJsonConstants.EIINFO_BLOCKS];
    if ( isAvailable( value ) ){
    	for( var bIds in value ) 	{    		 
    		 var block = Json2EiInfo.parseBlock( bIds, value[bIds] );
    		 eiInfo.addSheet( block );
    	};	
    };
    return eiInfo;
};

/**
 * <p>解析列表数据</p>
 * @private
 * @param {String}
 *            sId  sheet ID 
 * @param {Object}
 *            blockJson 列表数据，用Sheet ID取得
 */
Json2EiInfo.parseBlock = function(sId, blockJson){
	
	var sheet;
	var value = blockJson[EiInfoJsonConstants.BLOCK_META];
	if ( isAvailable( value ) ){
		var blockMeta = Json2EiInfo.parseBlockMeta(sId, value);
		sheet = new zxt.data.DataSheet(blockMeta);
	} else {	
	  sheet = new zxt.data.DataSheet(sId);
	};
	
	var value = blockJson[EiInfoJsonConstants.ATTRIBUTES];
  if ( isAvailable( value ) ){
    	sheet.attrs( value );
  };  
  
  var value = blockJson[EiInfoJsonConstants.BLOCK_DATA];
  if ( isAvailable( value ) ){
    sheet._rows = value;
  };
  return sheet;
};

/**
 * <p>解析列表头</p>
 * @private
 * @param {String}
 *            sId
 * @param {Object}
 *            blockJson
 */
Json2EiInfo.parseBlockMeta = function(sId, blockJson){
	var blockMeta = new zxt.data.DataSheetMeta(sId);
	var value = blockJson[EiInfoJsonConstants.BLOCK_META_DESC];
	if ( isAvailable( value ) ){
		blockMeta.setDesc(value);
	};
	var value = blockJson[EiInfoJsonConstants.ATTRIBUTES];
	if ( isAvailable( value ) ){
		blockMeta.attrs(value);
	};
	var value = blockJson[EiInfoJsonConstants.BLOCK_META_COLUMNLIST];
    if ( isAvailable( value )){
    	for( var bIds in value ){    		  		 
    		 var column = Json2EiInfo.parseColumn( value[bIds] );
    		 blockMeta.addColumn( column );
    	};	
    };	
	return blockMeta;
};

/**
 * <p>解析列表头中的列头属性</p>
 * @function
 * @private
 * @param {Object}
 *            blockJson
 */
Json2EiInfo.parseColumn = function(blockJson){

	var column = new zxt.data.DataSheetColumn(blockJson.name);
	
	var value = blockJson[EiInfoJsonConstants.ATTRIBUTES];
	if ( isAvailable( value ) ){
		column.attrs(value);
	};
	
    for( var iKey in blockJson ){
		var columnValue = blockJson[iKey];
		column[iKey] = columnValue;
		// eval("column." + iKey + "='" + columnValue + "'");
	};  
   
	return column;
}; 

/**
 * <p>JS端同JAVA端数据交互方法集</p>
 */
var EiCommunicator = {
	
	setToken : function(dw){
		if ( $zxt.TOKEN ){
			var token = dw.get("token");		
			$zxt.setToken(token);
		};
	},

	//AJAX 方式
	commit   : function(sMethod, sEiInfo, sCallback, sAsync) {		
		var async = sAsync;
		var jsonEi = EiInfo2Json.EiInfo2JsonString(sEiInfo);
		var instance = this;
		$zxt.lock(5000);//展示滚动条
		var endp = "/" + zxt.cfg.CONTEXT + zxt.cfg.AJAX_URL;//"/ZXT/loc.ajax"
		if ( $zxt.TOKEN ){
			var _token = $zxt.getToken();
			if ( zxt.util.isValue(_token) ){
				endp = endp + "?token=" + _token;
			};
		};
		
		$.ajax({
			type: "POST",//请求方式
			async: async,//false,要等待结果返回
			url:   endp,//发送请求的地址
			data: {	page: $zxt.PAGE, method: sMethod,	data: jsonEi },//发送到服务器的数据。将自动转换为请求字符串格式
			dataType: "json",//返回 JSON 数据
			dataFilter: function(data, type){//给Ajax返回的原始数据的进行预处理的函数
   			if ( $zxt.XSS ){
					data = zxt.util.stringXSSFilter(data);
				};
   			return data;
   		},
			success: function(msg){//请求成功后的回调函数
				$zxt.unlock();				
				var parsedEi = Json2EiInfo.parseJsonObject( msg );
				var _url = parsedEi.url(); 
				var _method = parsedEi.method(); 
				EiCommunicator.setToken(parsedEi);//setToken				
				
				if (zxt.util.isAvailable(_url)){
					EiCommunicator.submitURL(_url, parsedEi, _method);//页面跳转 forward
				} else {
					sCallback.onSuccess(parsedEi);
				};	
			},
			error: function(xml,eType,e){//在请求出错时调用
				$zxt.unlock();                   	
				sCallback.onFailure(xml,eType,e);
			}
		});
	},
	
	send   : function(sService, sMethod, sEiInfo, sCallback, sAsync) {		
		var async = sAsync;
		var jsonEi = EiInfo2Json.EiInfo2JsonString(sEiInfo);
		var instance = this;
		$zxt.lock(5000);
		var endp = "/" + zxt.cfg.CONTEXT + zxt.cfg.AJAX_URL;
		if ( $zxt.TOKEN ){
			var _token = $zxt.getToken();
			if ( zxt.util.isValue(_token) ){
				endp = endp + "?token=" + _token;
			};
		};
		
		$.ajax({
   			type: "POST",
   			async: async,
   			url:   endp,
   			data: {	service: sService, method: sMethod,	data: jsonEi },
   			dataType: "json",
   			dataFilter: function(data, type){
   				if ( $zxt.XSS ){
						data = zxt.util.stringXSSFilter(data);
					};
   				return data;
   			},
   			success: function(msg){
   				$zxt.unlock();   				
   	  		var parsedEi = Json2EiInfo.parseJsonObject( msg );
   	  		EiCommunicator.setToken(parsedEi);
   	  			
   	  		var _url = parsedEi.url(); 
   	  		if (zxt.util.isAvailable(_url)){
   	  			var _endp = "/" + zxt.cfg.CONTEXT + "/" + _url;
   	  			if ( $zxt.TOKEN ){
	   	  			if ( zxt.util.isValue($zxt.token) ){
								_endp = _endp + "?token=" + $zxt.token;
							};
						};
   	  			location.href = _endp;
   	  		};	
   	  			
        	sCallback.onSuccess(parsedEi);
    		},
   			error: function(xml,eType,e){
   				$zxt.unlock();                   	
        		sCallback.onFailure(xml,eType,e);
    		}
 		});
	},
	
	submitURL : function(url, dw, md, target) {//页面跳转
		var method = md || "onInitialize";
		var _strDW = EiInfo2Json.EiInfo2JsonString(dw);
		
		var _form = document.createElement("FORM");
		document.body.appendChild(_form);
		_form.method = "POST";
		
		if(zxt.util.isValue(target)){	
			_form.target = target;
		};
		
		var _methodE = $("<input name='method' type='hidden'>").val(method);
		_form.appendChild(_methodE.get(0));
		
		var _dataE = $("<input name='data' type='hidden'>").val(_strDW);
		_form.appendChild(_dataE.get(0));
		
		var endp = "/" + zxt.cfg.CONTEXT + "/" + url;
		if ( $zxt.TOKEN ){//默认是false
			var _token = $zxt.getToken();
			if ( zxt.util.isValue(_token) ){
				if ( zxt.util.stringContains(url, "?") ){
					endp = endp + "&token=" + _token;
				} else {
					endp = endp + "?token=" + _token;
				};			
			};
		};

		_form.action= endp;
		_form.submit();	
	},
	
	submit : function(location, page, dw, md, target) {
		var method = md || "onInitialize";
		var _strDW = EiInfo2Json.EiInfo2JsonString(dw);
		
		var _form = document.createElement("FORM");
		document.body.appendChild(_form);
		_form.method = "POST";
		
		if(zxt.util.isValue(target)){	
			_form.target = target;
		};
		var _methodE = $("<input name='method' type='hidden'>").val(method);
		_form.appendChild(_methodE.get(0));
		
		var _dataE = $("<input name='data' type='hidden'>").val(_strDW);
		_form.appendChild(_dataE.get(0));
		
		var endp = "/" + zxt.cfg.CONTEXT + "/" + location + zxt.cfg.FOWARD_URL + "?page=" + page;
		if ( $zxt.TOKEN ){
			var _token = $zxt.getToken();
			if ( zxt.util.isValue(_token) ){
				endp = endp + "&token=" + _token;
			};
		};
		
		_form.action= endp;
		_form.submit();	
	}			
	
};	

